
import './index.scss';

class Calendar extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      open: false,
      calendarHeight: 0,
      xy: '',
      only: true,
      activeRow: 0,
      monthView: false,
      monthHTML: false,
      monthHeight: 0,
      target: false,
      date: '',
      time: this.props.date.toISOString().slice(0,7)
    }
  }

  // DOM树渲染前
  componentWillMount() {
    let month = [];
    for(let i = -1; i < 3; i += 1) {
      month.push(this.makeCalendar((new Date(this.props.date).setMonth(this.props.date.getMonth() + i))));
    }
    
    this.setState({
      xy: [],
      monthView: true,
      monthHTML: month,
      date: new Date(this.props.date)
    });
  }

  activeRow(DateObj) {
    let cloneDate = new Date(DateObj.getTime());
    let time  = {
      days: cloneDate.getDate(),
      week: cloneDate.getDay(),
      firstDay: new Date(cloneDate.setDate(1)),
      xy: {
        x: 0,
        y: 0
      }
    }
    time.firstDatWeek = time.firstDay.getDay();
    let firstDatWeek = time.days - (7 - (time.firstDatWeek === 0 ? 7 : time.firstDatWeek));
    if (firstDatWeek < 1) {
      time.xy.x = time.week - time.firstDatWeek;
      time.xy.y = 0;
    } else {
      time.xy.x = time.week;
      if (firstDatWeek % 7 === 0) {
          time.xy.y = firstDatWeek / 7 - 1;
        } else {
          time.xy.y = firstDatWeek < 1 ? Math.floor(firstDatWeek / 7) - 1 :  Math.floor(firstDatWeek / 7) + 1;
        }
    }
    return time.xy;
  }

  componentDidMount () {
    // 记录天数的高度=>动画
    if (this.state.monthView) {
      if (this.state.only) {
        let month = document.getElementsByClassName('month');
        // 记录高度
        this.state.monthHeight = month[0].clientHeight;
        this.state.rowHeight = month[0].children[0].clientHeight;
        this.state.titleHeight = this.refs.title.clientHeight;
        this.state.weekHeight = this.refs.week.clientHeight;

       

        this.refs.calendar.style.height = this.state.titleHeight + this.state.rowHeight + this.state.weekHeight + 'px';

        this.state.sort = [month[0], month[1], month[2], month[3]];

        for (let i = 0, j = -100, len = this.state.sort.length; i < len; i += 1, j += 100) {
          this.state.sort[i].style.transform = `translateX(${j}vw)`;
          if (i === 1) {
            if (this.state.monthHeight !== this.state.sort[i].clientHeight) {
              this.refs.calendar.style.height = this.state.titleHeight + this.state.weekHeight + this.state.sort[i].clientHeight + 'px';
            }
            this.state.sort[i].style.zIndex = 2;
          } else {
            this.state.sort[i].style.zIndex = 1;
          }
        }
        this.setState({
          only: false
        })

        getElementsAttr(this.refs.monthView, 'span', 'data-date', this.props.date.toISOString().slice(0, 10), function(Data){
          Data.className = 'active';
          this.state.activeRow = Data.parentNode.parentNode.getAttribute('data-row');
          this.state.target = Data;
        }.bind(this));

        function getElementsAttr(document, tag, attr, value, callBack) {
          let DOMs = document.getElementsByTagName(tag);
          for (let i = 0, len = DOMs.length; i < len; i += 1) {
            if (DOMs[i].getAttribute(attr) === value) {
              let element = DOMs[i];
              callBack(element);
            }
          }
        }
      }
    }
  }



  // 制作日历
  makeCalendar(DateObj) {
    // 计算这个月的第一天和最后一天
    let firstDaylastDay = function(DateObj) {
      let cloneDate = new Date(DateObj);
      let Obj = {
        first: new Date(cloneDate).setDate(1),
        last: new Date(new Date(cloneDate).setMonth(cloneDate.getMonth() + 1)).setDate(1)-86400000
      };
      return {
        first: Obj.first,
        last: Obj.last,
        firstDayWeek: new Date(Obj.first).getDay(),
        days: new Date(Obj.last).getDate(),
        date: cloneDate
      };
    };

    // 计算这个月以七天为一行所要的行数
    let weekRows = function(firstDayAndLastDay) {
      let time = {
          week: firstDayAndLastDay.firstDayWeek,
          days: firstDayAndLastDay.days
        };
      time.sunday = time.week === 0 ? true : false;
      time.days = time.days-(7-time.sunday === 0 ? 7 : time.sunday);
      if (time.days % 7 !== 0) {
        return time.sunday ? Math.floor(time.days / 7) + 1 :  Math.floor(time.days / 7) + 2
      } else {
        return time.sunday === 0 ? time.days / 7 : time.days / 7 + 1;
      }
    };


    // 绘制这个月的每一天
    let makeDay =  function(firstDayAndLastDay, rows) {
      let time = {
        week: firstDayAndLastDay.firstDayWeek,
        days: firstDayAndLastDay.days,
        num: 0,
        make: [],
        date: firstDayAndLastDay.date.toISOString().slice(0,7)
      };

      // 拼接 HTML
      for (let i = 0, l = rows; i < l ; i += 1) {
        let day = [];
        day.push(`<ul data-row="${i}">`);

        for (let ii = 0; ii < 7; ii += 1) {
          time.week !== 0 && (
            ii = time.week,
            time.week = 0
          );

          if (time.num >= time.days) {
            break;
          }

          day.push(`<li><span data-date=${time.date}-${ time.num < 9 ? `0${time.num + 1}`: time.num + 1}>${++time.num}</span></li>`);
        }

        day.push('</ul>');
        time.make[time.make.length] = day.join('');
      }

      return time.make.join('');
    }

    let cloneDate = firstDaylastDay(DateObj);

    return makeDay(cloneDate, weekRows(cloneDate));
  }

  // 记录触摸屏幕的起始坐标
  touchstart(E) {
    this.state.xy = [E.touches[0].clientX, E.touches[0].clientY];
    E.preventDefault();
  }

  touchend(E) {
    let x = this.state.xy[0] - E.changedTouches[0].clientX,
        y = this.state.xy[1] - E.changedTouches[0].clientY;

    slippageX.call(this, x, y);

    // 左右滑动
    function slippageX(x, y) {
      if (200 < x || x < -200) {
        // 判断是否展开
        // if(!this.state.open) {
        //   this.refs.day.style.width = '600vw';
        //   this.refs.day.className = 'calendar-day single';
        // }
        if (200 < x) { // 左滑
          this.state.sort.push(this.state.sort[0]);
          this.state.sort.shift();
          for (let i = 0, j = -100, len = this.state.sort.length; i < len; i += 1, j += 100) {
            this.state.sort[i].style.transform = `translateX(${j}vw)`;
            this.state.sort[i].style.zIndex = 2;
            if (j === 0) {
              if (this.state.monthHeight !== this.state.sort[i].clientHeight) {
                this.state.monthHeight = this.state.sort[i].clientHeight;
                this.refs.calendar.style.height = this.state.titleHeight + this.state.weekHeight + this.state.monthHeight + 'px';
              }
            } else if (i === 3) {
              this.state.sort[i].style.zIndex = 1;
            }
          }
          let date = new Date(this.state.date.setMonth(this.state.date.getMonth() + 1));
          this.state.sort[3].innerHTML = this.makeCalendar(new Date(date).setMonth(date.getMonth() + 2));
          this.setState({
            time: date.toISOString().slice(0, 7),
            date: date
          });
        } else { // 右滑
          this.state.sort.unshift(this.state.sort[this.state.sort.length - 1]);
          this.state.sort.pop();
          for (let i = 0, j = -100, len = this.state.sort.length; i < len; i += 1, j += 100) {
            this.state.sort[i].style.transform = `translateX(${j}vw)`;
            this.state.sort[i].style.zIndex = 2;
            if (j === 0) {
              if (this.state.monthHeight !== this.state.sort[i].clientHeight) {
                this.state.monthHeight = this.state.sort[i].clientHeight;
                this.refs.calendar.style.height = this.state.titleHeight + this.state.weekHeight + this.state.monthHeight + 'px';
              }
            } else if (i === 0) {
              this.state.sort[i].style.zIndex = 1;
            }
          }
          let date = new Date(this.state.date.setMonth(this.state.date.getMonth() - 1));
          this.state.sort[0].innerHTML = this.makeCalendar(new Date(date).setMonth(date.getMonth() -1));
          this.setState({
            time: date.toISOString().slice(0, 7),
            date: date
          });
        }
      } else {
        slippageY.call(this, y)
      }
    }

    // 上下滑动
    function slippageY(y){
      if ( y > 30 || y < -30) {
        // this.refs.day.style.width = '100vw';
        // this.refs.day.className = 'calendar-day';
        // this.refs.day.style.transition = 'transform 1s';
        if (y > 30) { // 向上滑动
          this.refs.monthView.style.transform = `translateY(${-this.state.activeRow * this.state.rowHeight}px)`;
          this.state.open = false;
          this.refs.calendar.style.height = `${this.state.titleHeight + this.state.rowHeight + this.state.weekHeight}px`;
        } else { // 向下滑动
          this.state.open = true;
          this.refs.calendar.style.height = `${this.state.titleHeight + this.state.monthHeight + this.state.weekHeight}px`;
          this.refs.monthView.style.transform = '';
        }
      }
    }

    E.preventDefault();
  }

  dayClick(E) {
    if(E.target.nodeName === 'SPAN') {
      // 记录被激活的行数=> 动画
      this.state.activeRow = E.target.parentElement.parentElement.dataset.row;
      // 缓存上次目标
      this.setState({
        target: E.target
      });
      // 如果上次目标被记录
      this.state.target && (
        this.state.target.className = '',
        E.target.className = 'active'
      );
    }
  }

  mousedown(E) {
    E.preventDefault()
  }

  mouseup(E) {
    E.preventDefault()
  }

  mousemove(E) {
    E.preventDefault()
  }

  click(E) {
    E.preventDefault()
  }
  render() {
    return (
      <div className="calendar single" ref="calendar" onMouseDown={this.mousedown.bind(this)} onMouseUp={this.mouseup.bind(this)} onMouseMove={this.mousemove.bind(this)} onClick={this.click.bind(this)}>
        <div className="calendar-mobile" onTouchStart={this.touchstart.bind(this)} onTouchEnd={this.touchend.bind(this)}>
          <p className="calendar-title" ref='title' dangerouslySetInnerHTML={{__html: this.state.time}}></p>
          <ul className="calendar-week" ref="week">
            <li>周日</li>
            <li>周一</li>
            <li>周二</li>
            <li>周三</li>
            <li>周四</li>
            <li>周五</li>
            <li>周六</li>
          </ul>
          { 
            this.state.monthView
            ? <div onTouchStart={this.dayClick.bind(this)} className="monthView" ref="monthView">
                <div className="month" dangerouslySetInnerHTML={{__html: this.state.monthHTML[0]}}></div>
                <div className="month" dangerouslySetInnerHTML={{__html: this.state.monthHTML[1]}}></div>
                <div className="month" dangerouslySetInnerHTML={{__html: this.state.monthHTML[2]}}></div>
                <div className="month" dangerouslySetInnerHTML={{__html: this.state.monthHTML[3]}}></div>
              </div>

            : ''
          }
        </div>
      </div>
    )
  }
}

export default Calendar;